老實說從這一節開始,就是一個我也很不確定的領域了(抖)。Functor、Applicative、Monad 這三者之間的關係可以說是 FP 中最曲折離奇的部分,難倒了許許多多的英雄好漢。不過我還是盡量在我所理解的範圍內跟大家說明這些名詞的概念,有錯的話還請多多包涵,願意跟我討論的話也是十分歡迎。
 
在我的認知中,Functor 是一種計算語境(computational context)(有讀者要抗議了:你怎麼拿一個看不懂的名詞去解釋另一個看不懂的名詞?)。我們可以把 Functor 當作包含上下文(context)的運算。
 
舉個最常見的例子:JavaScript 的 Promise。

注意!JS 的 Promise 並不是 Functor。
我們會在後續說明他為什麼不是 Functor,這裏只是要先說明 context 的概念。

我們知道 Promise 可以透過 then 接收一個 callback,計算的結果會被傳入 callback 執行。Promise 的建構子會執行一個函數,並且在失敗或成功時呼叫 resolve 或 reject。也就是說,then 的參數裡面的 callback 函數,有可能會收到成功或失敗的結果,而這個會失敗的可能性就是所謂的 context
 
前幾天很認真看的同學應該會發現,如果所有 data 都是 immutable,那理論上用這樣子寫出來的程式不應該會執行失敗,因為所有 symbol 的值都早在編譯時期就可以藉由綁定決定好了。
 
然而在有任何 I/O 發生時,就有可能會有失敗的情況,如使用者輸入不符合我們要的格式,或是 network I/O 斷線 ...... 等等。
 
Functor 的計算語境就是在指這種狀態。
 
以 Haskell 為例的話,在 Haskell 中有三種 data type(可以想像成 OOP 中的 class),分別是 Maybe、Just 跟 Nothing。 Maybe 的定義如下:

data Maybe a = Just a | Nothing


也就是說 Maybe a (a 為任意型態)只可能是 Just aNothing。我們可以把 Nothing 想像成類似 JS 的 null ,所以假設 JS 一個 Promise 的回傳值會固定有一種型別,例如一個 Promise resolve 成功時的結果型態會是 Int 的話,那我們就可以把這個 Promise 的回傳值型態當作是 Maybe Int,代表當他成功時值會是 Just Int,失敗時會是 Nothing(null),Maybe 隱含了運算(Promise)可能會失敗的 context。
 
Functor 還有一個特性是可以被 map-over ,也就是可以透過 fmap

fmap (a -> b) -> f a -> f b

去運算被包在 context 的值。用 Promise 想像的話就是,我們可以透過 then 的 callback 去運算 Promise 的結果。then callback 是一個普通、沒有包在 context 中的函數,卻可以作用在被包在 context 中的值 (Promise)之上,這就是 map over 的概念。
 

 
從這裏我們可以發現 Promise 借鏡了許多 Functor 的概念,然而他其實不滿足 Functor 的一些性質 (Associativity Law),可以參考這篇文章Are Promises Monads, Functor or Applicative
 
* 本文圖片來自這裏

#Functional Programming #電腦程式







你可能感興趣的文章

.Net MVC authorization Controller and Workcontext extension in razor view

.Net MVC authorization Controller and Workcontext extension in razor view

Flex Panels Image Gallery

Flex Panels Image Gallery

OOP 15 - Interface Segregation Principles

OOP 15 - Interface Segregation Principles






留言討論